package cn.gameback.supervisionservices.service.impl;

import cn.gameback.supervisionservices.dto.User.LeaderCrewDTO;
import cn.gameback.supervisionservices.dto.User.RoleTableDTO;
import cn.gameback.supervisionservices.entity.LeaderCrew;
import cn.gameback.supervisionservices.entity.Role;
import cn.gameback.supervisionservices.entity.UserRole;
import cn.gameback.supervisionservices.mapper.LeaderCrewMapper;
import cn.gameback.supervisionservices.mapper.RoleMapper;
import cn.gameback.supervisionservices.mapper.UserRoleMapper;
import cn.gameback.supervisionservices.util.BusinessException;
import cn.gameback.supervisionservices.util.Result;
import cn.gameback.supervisionservices.vo.RequestVo.UserVo.*;
import cn.gameback.supervisionservices.mapper.UserMapper;
import cn.gameback.supervisionservices.service.UserService;
import cn.gameback.supervisionservices.entity.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.sf.jsqlparser.expression.TryCastExpression;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yaml.snakeyaml.constructor.DuplicateKeyException;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private LeaderCrewMapper leaderCrewMapper;

    // 用户登录方法
    @Override
    public Result<User> loginFun(LoginQuery loginQueryRequest) {

        if (loginQueryRequest.getUserName() != null && loginQueryRequest.getPassword() != null) {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("userName", loginQueryRequest.getUserName());
            queryWrapper.eq("password", loginQueryRequest.getPassword());

            User user = userMapper.selectOne(queryWrapper);

            if (user != null) {
                return new Result<>(user);
            } else {
                // 账号密码错误
                return new Result<>(401, "账号密码错误");
            }
        } else {
            // 用户名或密码不能为空
            return new Result<>(400, "用户名或密码不能为空");
        }
    }

    // 用户注册方法
    @Override
    public Result<User> registerFun(RegisterQuery registerQueryRequest) {
        // 检查账号、密码、手机号是否有值
        if (registerQueryRequest.getUserName() == null || registerQueryRequest.getPassword() == null || registerQueryRequest.getPhone() == null) {
            return new Result<>(401, "账号、密码或手机号不能为空");
        }

        // 查询数据库中是否已存在相同账号或手机号的用户
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("account", registerQueryRequest.getUserName())
                .or()
                .eq("phone_number", registerQueryRequest.getPhone());

        User existingUser = userMapper.selectOne(queryWrapper);
        if (existingUser != null) {
            // 如果存在，则返回错误信息
            return new Result<>(401, "账号或手机号已存在");
        }

        // 创建新用户对象并设置属性
        User newUser = new User();
        newUser.setUserName(registerQueryRequest.getUserName());
        newUser.setPassword(registerQueryRequest.getPassword()); // 注意：这里应该对密码进行加密处理
        newUser.setPhone(registerQueryRequest.getPhone());
        // 设置其他必要的属性

        // 插入新用户到数据库
        int result = userMapper.insert(newUser);

        if (result > 0) {
            // 注册成功
            return new Result<>(200, "注册成功");
        } else {
            // 注册失败
            return new Result<>(401, "注册失败，请稍后再试");
        }
    }

    @Override
    public User getUserById(Integer id) {
        return userMapper.getUserById(id);
    }

    @Override
    public Result<List<RoleTableDTO>> getRoleTable(RoleQuery roleQueryRequest) {
        // 获取需要查询的角色 教师？ 组长？ 还是组员
        String roleName = roleQueryRequest.getRoleName();

        // 查询的角色 是否有值 没有值 就返回403 表示拒绝用户请求
        if (roleName == null || roleName.isEmpty()) {
            return new Result<>(403, "拒绝请求！");
        }
        // 查询对应角色的id是什么？
        Integer roleId = roleMapper.getRoleIdByDescription(roleName);

        System.out.println("查询的 roleId = " + roleId);
        // 查询出所有拥有该角色的用户 在user_role 表中
        List<UserRole> userRoles = userRoleMapper.getUserRolesByRoleId(roleId);

        // 将这些用户id 在user表中 查询出nickName
        List<Integer> userIds = userRoles.stream()
                .map(UserRole::getUserId)
                .collect(Collectors.toList());
        // 查询出这些用户的nickName
        List<User> users = userMapper.selectBatchIds(userIds);
        // 封装成RoleTableDTO
        List<RoleTableDTO> roleTableDTOList = new ArrayList<>();
        for (User user : users) {
            RoleTableDTO roleTableDTO = new RoleTableDTO();
            roleTableDTO.setId(user.getId());
            roleTableDTO.setName(user.getNickName());
            roleTableDTOList.add(roleTableDTO);
        }

        return new Result<>(roleTableDTOList);
    }

    /**
     * 分页获取用户列表
     * @param userQueryRequest
     * @return
     */
    @Override
    public IPage<User> getAllUsers(UserQuery userQueryRequest) {
        Page<User> userPage = new Page<>(userQueryRequest.getCurrent(), userQueryRequest.getpageSize());
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();

        queryWrapper.select(
                "id",
                "userName",
                "nickName",
                "email",
                "avator",
                "phone",
                "created_at",
                "updated_at"
        );

        // 模糊搜索 账号
        if (userQueryRequest.getUserName() != null && !userQueryRequest.getUserName().isEmpty()) {
            queryWrapper.like("userName", userQueryRequest.getUserName());
        }

        // 模糊搜素 姓名
        if (userQueryRequest.getNickName() != null && !userQueryRequest.getNickName().isEmpty()) {
            queryWrapper.like("nickName", userQueryRequest.getNickName());
        }

        // 模糊搜素 邮箱
        if (userQueryRequest.getEmail()!= null && !userQueryRequest.getEmail().isEmpty()) {
            queryWrapper.like("email", userQueryRequest.getEmail());
        }

        // 模糊搜素 手机号码
        if (userQueryRequest.getPhone() != null && !userQueryRequest.getPhone().isEmpty()) {
            queryWrapper.like("phone", userQueryRequest.getPhone());
        }

        // 查询用户数据
        IPage<User> userPageResult = userMapper.selectPage(userPage, queryWrapper);

        // 获取并设置角色和上级信息
        List<User> users = userPageResult.getRecords();
        List<Integer> userIds = users.stream().map(User::getId).collect(Collectors.toList());

        // 提前查询所有相关角色描述
        List<UserRole> allUserRoles = userRoleMapper.selectList(new QueryWrapper<UserRole>().in("userId", userIds));
        Map<Integer, List<String>> roleDescriptionMap = allUserRoles.stream()
                .collect(Collectors.groupingBy(UserRole::getUserId,
                        Collectors.mapping(userRole -> roleMapper.getDescriptionByRoleId(userRole.getRoleId()), Collectors.toList())));

        // 处理上级信息
        // 1. 查询所有用户的leaderId映射
        List<LeaderCrewDTO> leaderCrewList = leaderCrewMapper.findLeaderIdsByUserIds(userIds);
        System.out.println("leaderCrewList" + leaderCrewList);
        Map<Integer, List<Integer>> userLeaderMap = leaderCrewList.stream()
                    .collect(Collectors.groupingBy(LeaderCrewDTO::getUserId,
                        Collectors.mapping(LeaderCrewDTO::getLeaderId, Collectors.toList())));

        // 2. 收集所有leaderId并查询用户信息
        List<Integer> allLeaderIds = leaderCrewList.stream()
                .map(LeaderCrewDTO::getLeaderId)
                .distinct()
                .collect(Collectors.toList());
        Map<Integer, User> leaderMap = new HashMap<>();
        if (!allLeaderIds.isEmpty()) {
            // 使用 QueryWrapper 指定查询字段
            QueryWrapper<User> wrapper = new QueryWrapper<User>()
                    .select(
                            "id",
                            "nickName"
                    )
                    .in("id", allLeaderIds);  // 添加 IN 条件

            // 执行查询
            List<User> leaders = userMapper.selectList(wrapper);
            leaderMap = leaders.stream()
                    .collect(Collectors.toMap(User::getId, Function.identity()));
        }

        // 设置角色和上级信息
        for (User user : users) {
            // 角色描述
            List<String> roleDescriptions = roleDescriptionMap.getOrDefault(user.getId(), Collections.emptyList());
            user.setRoleDescriptions(roleDescriptions);

            // 上级信息
            List<Integer> leaderIds = userLeaderMap.getOrDefault(user.getId(), Collections.emptyList());
            List<User> leaders = leaderIds.stream()
                    .map(leaderMap::get)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            user.setLeaders(leaders);
        }
        return userPageResult;
    }

    @Override
    public void saveUser(User user) {
        userMapper.saveUser(user);
    }

    @Override
    public void updateUser(User user) {
        userMapper.updateUser(user);
    }

    @Transactional
    @Override
    public Result updateUserLeader(LeaderCrewQuery query) {
        Integer crewId = query.getCrewId();
        List<Integer> leaderId = query.getLeaderId();

        // 1. 参数校验
        if (crewId == null) {
            throw new IllegalArgumentException("memberId cannot be null");
        }

        // 2. 删除旧数据
        int deletedRows = leaderCrewMapper.deleteByMemberId(crewId);
        log.info("Deleted {} rows for memberId: {}", deletedRows, crewId);

        // 3. 插入新数据
        if (leaderId != null && !leaderId.isEmpty()) {
            try {
                leaderCrewMapper.batchInsert(crewId, leaderId);
                log.info("Inserted {} leaderIds for memberId: {}", leaderId.size(), crewId);
            } catch (DuplicateKeyException e) {
                // 处理唯一约束冲突（例如重复插入）
                System.out.println(e);
                throw new BusinessException("Leader ID list contains duplicates", e);
            }
        }
        return new Result<>(200, "更新成功");
    }

    @Override
    public void deleteUser(Integer id) {
        userMapper.deleteUser(id);
    }
}